package com.ysstech.common.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Random;
import java.util.UUID;
import java.util.regex.Pattern;

import com.ysstech.common.enums.YssEnum;
import com.ysstech.common.enums.YssRegularEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateUtils;

/**
 * 时间工具
 */
@Slf4j
public class DateUtil {

    /**
     * 判断时间是否超过24小时
     *
     * @param start
     * @param end
     * @return
     * @throws Exception
     */
    public static boolean judgmentDate(Date start, Date end) throws Exception {
        long cha = end.getTime() - start.getTime();
        if (cha < 0) {
            return false;
        }
        double result = cha * 1.0 / (1000 * 60 * 60);
        if (result <= 24) {
            return false;
        } else {
            return true;
        }
    }

    /**
     * 获取当前年份
     *
     * @return
     */
    public static String getSysYear() throws Exception {
        Calendar calendar = Calendar.getInstance();
        String year = String.valueOf(calendar.get(Calendar.YEAR));
        return year;
    }

    /**
     * 获取当前年份
     *
     * @return
     */
    public static String getSysYear(Date date) throws Exception {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        String year = String.valueOf(calendar.get(Calendar.YEAR));
        return year;
    }

    /**
     * 获取当前月份
     *
     * @return
     */
    public static String getSysMonth() throws Exception {
        Calendar date = Calendar.getInstance();
        String month = String.valueOf(date.get(Calendar.MONTH) + 1);
        return month;
    }

    /**
     * 获取当前月份
     *
     * @return
     */
    public static String getSysMonth(Date date) throws Exception {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        String month = String.valueOf(calendar.get(Calendar.MONTH) + 1);
        return month;
    }

    /**
     * 获取当前月份
     *
     * @return
     */
    public static String getSysMonth(String date) throws Exception {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(DateUtil.strToDate(date));
        String month = String.valueOf(calendar.get(Calendar.MONTH) + 1);
        return month;
    }

    /**
     * 通过时间生成随机数
     */
    public static synchronized String generateUUID() throws Exception {
        return UUID.randomUUID().toString().toUpperCase().replace("-", "");
    }

    public static synchronized String generateNumber() throws Exception {
        Date currentTime = new Date();
        SimpleDateFormat formatter = new SimpleDateFormat(YssEnum.YSS_DEFAULT_DATE_TIME_FORMAT1.getCode());
        String dateString = formatter.format(currentTime);
        Random random = new Random();
        int x = random.nextInt(9999 - 1000 + 1) + 1000;
        String y = String.valueOf(x);
        String numString = dateString + y;
        return numString;
    }


    public static final Date addDay(Date dDate, int days) throws Exception {
        return addDate(dDate, days, Calendar.DAY_OF_MONTH);
    }

    /**
     * 功能说明：加减月，根据日期向前或向后推算N个月
     *
     * @param dDate  日期
     * @param months 月份数 正整数或负整数
     * @return 返回增加月份后的日期对象
     */
    public static final Date addMonth(Date dDate, int months) throws Exception {
        return addDate(dDate, months, Calendar.MONTH);
    }

    /**
     * 功能说明：加减年，根据日期向前或向后推算N年
     *
     * @param dDate 日期
     * @param years 年份数 正整数或负整数
     * @return 返回增加年份后的日期对象
     */
    public static final Date addYear(Date dDate, int years) throws Exception {
        return addDate(dDate, years, Calendar.YEAR);
    }

    /**
     * 功能说明：加减年，根据日期向前或向后推算N年
     *
     * @param sDate 日期
     * @param years 年份数 正整数或负整数
     * @return 返回增加年份后的日期对象
     */
    public static final String addYear(String sDate, int years) throws Exception {
        return DateUtil.dateToStr(addDate(DateUtil.strToDate(sDate), years, Calendar.YEAR));
    }

    /**
     * 日期增加减少
     *
     * @param dDate
     * @return
     */
    public static Date addDate(Date dDate, int amount, int field) throws Exception {
        GregorianCalendar cl = new GregorianCalendar();
        cl.setTime(dDate);
        cl.add(field, amount);
        return cl.getTime();
    }

    /**
     * 字符串类型转换为时间类型
     *
     * @param str
     * @return
     */
    public static Date strToDate(String str) throws Exception {
        return strToDateByFormat(str, YssEnum.YSS_DEFAULT_DATE_TIME.getCode());
    }

    /**
     * 字符串类型转换为时间类型 按照给定格式
     *
     * @param str
     * @return
     */
    public static Date strToDateByFormat(String str, String format) throws Exception {
        if (StringUtils.isBlank(str)) {
            return null;
        }
        if (StringUtils.isBlank(format)) {
            format = YssEnum.YSS_DEFAULT_DATE_TIME.getCode();
        }
        Date date = null;
        try {
            date = new SimpleDateFormat(format).parse(str);
            return date;
        } catch (ParseException e) {
            throw new Exception("转换日期失败，请稍后重试！");
        }
    }

    /**
     * 日期转字符串
     *
     * @param date
     * @return
     * @throws Exception
     */
    public static String dateToStr(Date date) throws Exception {
        return new SimpleDateFormat(YssEnum.YSS_DEFAULT_DATE_TIME.getCode()).format(date);
    }

    /**
     * 日期转字符串 按照指定格式
     *
     * @param date
     * @param format
     * @return
     * @throws Exception
     */
    public static String dateToStrByFormat(Date date, String format) throws Exception {
        if (null == date) {
            return null;
        }
        if (StringUtils.isBlank(format)) {
            format = YssEnum.YSS_DEFAULT_DATE_TIME.getCode();
        }
        return new SimpleDateFormat(format).format(date);
    }

    /**
     * 字符串转 LocalDate类型
     *
     * @param date
     * @return
     * @throws Exception
     */
    public static LocalDate strToLocalDate(String date) throws Exception {
        if (StringUtils.isBlank(date)) {
            return null;
        }
        DateTimeFormatter df = DateTimeFormatter.ofPattern(YssEnum.YSS_DEFAULT_DATE_TIME.getCode());
        return LocalDate.parse(date, df);
    }

    /**
     * 字符串转 LocalDate类型 按照给定的格式
     *
     * @param date
     * @param format
     * @return
     * @throws Exception
     */
    public static LocalDate strToLocalDateByFormat(String date, String format) throws Exception {
        if (StringUtils.isBlank(date)) {
            return null;
        }
        if (StringUtils.isBlank(format)) {
            format = YssEnum.YSS_DEFAULT_DATE_TIME.getCode();
        }
        DateTimeFormatter df = DateTimeFormatter.ofPattern(format);
        return LocalDate.parse(date, df);
    }

    /**
     * LocalDate转字符串
     *
     * @param date
     * @return
     * @throws Exception
     */
    public static String localDateToStr(LocalDate date) throws Exception {
        if (null == date) {
            return null;
        }
        return DateTimeFormatter.ofPattern(YssEnum.YSS_DEFAULT_DATE_TIME.getCode()).format(date);
    }

    /**
     * LocalDate转字符串 按照给定的格式
     *
     * @param date
     * @param format
     * @return
     * @throws Exception
     */
    public static String localDateToStrByFormat(LocalDate date, String format) throws Exception {
        if (null == date) {
            return null;
        }
        if (StringUtils.isBlank(format)) {
            format = YssEnum.YSS_DEFAULT_DATE_TIME.getCode();
        }
        return DateTimeFormatter.ofPattern(format).format(date);
    }

    /**
     * LocalDateTime 类型转成String
     *
     * @param date
     * @return
     * @throws Exception
     */
    public static String localDateTimeToStr(LocalDateTime date) throws Exception {
        if (null == date) {
            return null;
        }
        return DateTimeFormatter.ofPattern(YssEnum.YSS_DEFAULT_DATE_TIME.getCode()).format(date);
    }

    /**
     * LocalDateTime 类型转成String
     *
     * @param date
     * @param format
     * @return
     * @throws Exception
     */
    public static String localDateTimeToStrByFormat(LocalDateTime date, String format) throws Exception {
        if (null == date) {
            return null;
        }
        if (StringUtils.isBlank(format)) {
            format = YssEnum.YSS_DEFAULT_DATE_TIME.getCode();
        }
        return DateTimeFormatter.ofPattern(format).format(date);
    }

    /**
     * String  类型转成 LocalDateTime
     *
     * @param date
     * @return
     * @throws Exception
     */
    public static LocalDateTime strToLocalDateTime(String date) throws Exception {
        if (StringUtils.isBlank(date)) {
            return null;
        }
        DateTimeFormatter df = DateTimeFormatter.ofPattern(YssEnum.YSS_DEFAULT_DATE_TIME.getCode());
        return LocalDateTime.parse(date, df);
    }

    /**
     * String  类型转成 LocalDateTime
     *
     * @param date
     * @param format
     * @return
     * @throws Exception
     */
    public static LocalDateTime strToLocalDateTimeByFormat(String date, String format) throws Exception {
        if (StringUtils.isBlank(date)) {
            return null;
        }
        if (StringUtils.isBlank(format)) {
            format = YssEnum.YSS_DEFAULT_DATE_TIME.getCode();
        }
        DateTimeFormatter df = DateTimeFormatter.ofPattern(format);
        return LocalDateTime.parse(date, df);
    }

    /**
     * 获取当年的第一天
     *
     * @return
     * @paramyear
     */
    public static Date getCurrYearFirst() {
        Calendar currCal = Calendar.getInstance();
        int currentYear = currCal.get(Calendar.YEAR);
        return getYearFirst(currentYear);
    }

    /**
     * 获取当年的最后一天
     *
     * @return
     * @paramyear
     */
    public static Date getCurrYearLast() {
        Calendar currCal = Calendar.getInstance();
        int currentYear = currCal.get(Calendar.YEAR);
        return getYearLast(currentYear);
    }

    /**
     * 获取某年第一天日期
     *
     * @paramyear年份
     * @returnDate
     */
    public static Date getYearFirst(int year) {
        Calendar calendar = Calendar.getInstance();
        calendar.clear();
        calendar.set(Calendar.YEAR, year);
        Date currYearFirst = calendar.getTime();
        return currYearFirst;
    }

    /**
     * 获取某年最后一天日期
     *
     * @paramyear年份
     * @returnDate
     */
    public static Date getYearLast(int year) {
        Calendar calendar = Calendar.getInstance();
        calendar.clear();
        calendar.set(Calendar.YEAR, year);
        calendar.roll(Calendar.DAY_OF_YEAR, -1);
        Date currYearLast = calendar.getTime();
        return currYearLast;
    }

    /**
     * 返回指定日期的季度
     *
     * @param date
     * @return
     */
    private static int getQuarterOfYear(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.MONTH) / 3 + 1;
    }

    /**
     * 功能说明：判断闰年
     *
     * @param year 传入得年份值
     * @return new GregorianCalendar().isLeapYear(year) 是否为闰年;
     */
    public static boolean isLeapYear(int year) {
        return new GregorianCalendar().isLeapYear(year);
    }

    /**
     * 功能说明：获取指定日期范围内的闰年数
     *
     * @param startDate：起始日期（包含）
     * @param endDate：结束日期（包含）
     * @return 指定日期范围内的闰年数
     */
    public static int getLeapYears(Date startDate, Date endDate) throws Exception {
        int leapDays = 0;
        for (int i = getYear(startDate); i <= getYear(endDate); i++) {
            if (isLeapYear(i)) {
                leapDays++;
            }
        }
        return leapDays;
    }

    /**
     * 功能说明：得到年份(月份getMonth，日getDay，星期getWeekDay)
     * 包装了GregorianCalendar类的get方法
     * Calendar类中定义了月份，星期几的常数。
     * 注意月份常数0开始，一般不要使用
     *
     * @param dDate 传日的日期对象
     * @return int年份
     */
    public static int getYear(Date dDate) {
        return getDateItems(dDate, Calendar.YEAR);
    }

    /**
     * 功能说明：得到年份(月份getMonth，日getDay，星期getWeekDay)
     * 包装了GregorianCalendar类的get方法
     * Calendar类中定义了月份，星期几的常数。
     * 注意月份常数0开始，一般不要使用
     *
     * @param dDate 传日的日期对象
     * @return int得到月份
     */
    public static int getMonth(Date dDate) {
        return getDateItems(dDate, Calendar.MONTH) + 1;
    }

    /**
     * 功能说明：得到年份(月份getMonth，日getDay，星期getWeekDay)
     * 包装了GregorianCalendar类的get方法
     * Calendar类中定义了月份，星期几的常数。
     * 注意月份常数0开始，一般不要使用
     *
     * @param dDate 传日的日期对象
     * @return int日
     */
    public static int getDay(Date dDate) {
        return getDateItems(dDate, Calendar.DAY_OF_MONTH);
    }

    /**
     * 功能说明：得到年份(月份getMonth，日getDay，星期getWeekDay)
     * 包装了GregorianCalendar类的get方法
     * Calendar类中定义了月份，星期几的常数。
     * 注意月份常数0开始，一般不要使用
     *
     * @param dDate 传日的日期对象
     * @return int星期几
     */
    public static int getWeekDay(Date dDate) {
        return getDateItems(dDate, Calendar.DAY_OF_WEEK);
    }

    public static final int getDateItems(Date dDate, int field) {
        GregorianCalendar cl = new GregorianCalendar();
        cl.setTime(dDate);
        return cl.get(field);
    }

    /**
     * 日期比较
     *
     * @param date1
     * @param date2
     * @return
     * @throws Exception
     */
    public static int differentDaysByDate(Date date1, Date date2) throws Exception {
        int days = 0;
        try {
            days = (int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24));
        } catch (Exception ex) {
            throw new Exception("日期比较失败，请稍后重试！");
        }
        return days;
    }

    /**
     * 日期比较
     *
     * @param date1
     * @param date2
     * @return
     * @throws Exception
     */
    public static int differentDaysByString(String date1, String date2) throws Exception {
        int days = 0;
        try {
            days = (int) ((DateUtil.strToDate(date2).getTime() - DateUtil.strToDate(date1).getTime()) / (1000 * 3600 * 24));
        } catch (Exception ex) {
            throw new Exception("日期比较失败，请稍后重试！");
        }
        return days;

    }

    /**
     * 当前日期
     */
    public static Date currentDate() {
        return new Date();
    }

    /**
     * 得到今天的起始时间
     */
    public static Date getTodayStartTime() {
        return getStartTimeOfDay(currentDate());
    }

    /**
     * 得到今天的结束时间
     */
    public static Date getTodayEndTime() {
        return getEndTimeOfDay(currentDate());
    }

    /**
     * 得到指定那天的起始时间点
     */
    public static Date getStartTimeOfDay(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    /**
     * 得到指定那天的终止时间点
     */
    public static Date getEndTimeOfDay(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(getStartTimeOfDay(date));
        calendar.add(Calendar.DAY_OF_MONTH, 1);
        calendar.add(Calendar.MILLISECOND, -1);
        return calendar.getTime();
    }

    /**
     * 获取所在月的第三个星期五
     *
     * @param time
     */

    private static void getWeekByDate(Date time) {

        SimpleDateFormat sdf = new SimpleDateFormat(YssEnum.YSS_DEFAULT_DATE_TIME.getCode()); // 设置时间格式
        Calendar cal = Calendar.getInstance();
        cal.setTime(time);
        // 判断要计算的日期是否是周日，如果是则减一天计算周六的，否则会出问题，计算到下一周去了
        int dayWeek = cal.get(Calendar.DAY_OF_WEEK);// 获得当前日期是一个星期的第几天
        int daymonth = cal.get(Calendar.MONTH); //日期所在月份
        if (1 == dayWeek) {
            cal.add(Calendar.DAY_OF_MONTH, -1);
        }
        log.info("要计算日期为:" + sdf.format(cal.getTime())); // 输出要计算日期
        cal.setFirstDayOfWeek(Calendar.MONDAY);// 设置一个星期的第一天，按中国的习惯一个星期的第一天是星期一
        int day = cal.get(Calendar.DAY_OF_WEEK);// 获得当前日期是一个星期的第几天
        cal.add(Calendar.DATE, cal.getFirstDayOfWeek() - day);//当前周所在周一
        String imptimeEnd = sdf.format(cal.getTime());
        cal.add(Calendar.DATE, 4);//4天当前周的周五
        int daymonth2 = cal.get(Calendar.MONTH); //周五所在的月份
        if (daymonth == daymonth2) { //第一个周五在当前月
            cal.add(Calendar.WEEK_OF_MONTH, 2);
        } else { //第一个周五不在当前月
            cal.add(Calendar.WEEK_OF_MONTH, 3);
        }
        imptimeEnd = sdf.format(cal.getTime());
        log.info("所在周星期五的日期：" + imptimeEnd);

    }

    private static String[] parsePatterns = {"yyyy-MM-dd", "yyyy年MM月dd日", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyyMMdd"};

    /**
     * 校验是否日期格式字符串
     *
     * @param string
     * @return
     */
    public static Date parseDate(String string) {
        if (string == null) {
            return null;
        }
        try {
            return DateUtils.parseDate(string, parsePatterns);
        } catch (ParseException e) {
            return null;
        }
    }

    /**
     * 校验是否yyyy-MM-dd HH:mm:ss日期格式字符串
     *
     * @param string
     * @return
     */
    public static Boolean checkStandardDate(String string) {
        if (string == null) {
            return false;
        }
        if (Pattern.matches(YssRegularEnum.DATE_TIME_REGULAR.getCode(), string)) {
            return true;
        }
        return false;
    }

    public static void main(String[] args) throws Exception {

      /*  //设置转换的日期格式
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        //开始时间
        Date startDate = sdf.parse("2019-02-28");
        //结束时间
        Date endDate = sdf.parse("2019-03-01");

        //得到相差的天数 betweenDate
        long betweenDate = (endDate.getTime() - startDate.getTime())/(60*60*24*1000);

        //打印控制台相差的天数
        log.info(betweenDate);
*/
        byte b1[] = {0x03};
        String str1 = new String(b1);
        log.info("abc" + str1 + "bcd");
        try {
            //  String values= "'H"+String.format("%0"+(5-"00728".length())+"d",0)+"00728"+"'";
        } catch (Exception ex) {
            log.error(ex.toString());
        }

    }


}
